package a5.function;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;

import a5.common.Token;

/**
 * A compilation of common functions and variables.
 * 
 * @author Jason Campos
 * @version Assignment 6, CS 152 (Programming Paradigms) Fall 2012, Jeffrey Smith
 */
public class Constants {
	/**
	 * Common variables
	 */
	public static final HashMap<String,String> variables = new HashMap<>();
	
	/**
	 * Common functions
	 */
	public static final HashMap<String,Function> functions = new HashMap<>();
	static {	
		// Addition of two numbers
		functions.put("+", new Function(){
			@Override
			public String invoke(LinkedList<String> arguments){
				// This implementation of "+" is only able to add two numbers at a time.
				if(arguments.size() != 2)
					throw new IllegalArgumentException("arity mismatch. '+' expected 2 arguments. Received " + arguments.size());
				
				// Tokenize the argument strings and perform an assertion 
				// that the arguments are in fact IntegerLiteral. 
				Iterator<Token> i = Token.tokenize(arguments).iterator();
				Token t1 = i.next();
				Token t2 = i.next();
				
				Token.assertType(t1, "IntegerLiteral");
				Token.assertType(t2, "IntegerLiteral");

				// Use the build in + operator to get the result and return as a String				
				int result = Integer.parseInt(t1.getSpelling()) + Integer.parseInt(t2.getSpelling());
				return String.valueOf(result);
			}
		});
		
		// Difference of two numbers
		functions.put("-", new Function(){
			@Override
			public String invoke(LinkedList<String> arguments) {
				// This implementation of "-" is only able to add two numbers at a time.
				if(arguments.size() != 2)
					throw new IllegalArgumentException("arity mismatch. '-' expected 2 arguments. Received " + arguments.size());
			
				// Tokenize the argument strings and perform an assertion 
				// that the arguments are in fact IntegerLiteral. 
				Iterator<Token> i = Token.tokenize(arguments).iterator();
				Token t1 = i.next();
				Token t2 = i.next();
				
				Token.assertType(t1, "IntegerLiteral");
				Token.assertType(t2, "IntegerLiteral");
				
				// Use the build in - operator to get the result and return as a String
				int result = Integer.parseInt(t1.getSpelling()) - Integer.parseInt(t2.getSpelling());
				return String.valueOf(result);
			}
		});
	}
}
